<script setup lang="ts">
import type { FormInstance, FormItemRule, FormRules } from 'element-plus'

import SlideVerify from '@/components/slide-verify.vue'
import { useRegister, useSendSms } from '@fl/api/mall-api'
import { SubmitBtn } from '@fl/components'
import { useMessage } from '@fl/hooks/web/use-message'

import PolicyAgreement from './policy-agreement.vue'
import ServiceAgreement from './service-agreement.vue'

const { createMessage } = useMessage()
const verifyVisible = ref(false)
const serviceVisible = ref(false)
const policyVisible = ref(false)
const verifyRef = ref()

const { push } = useRouter()

type IForm = {
    account: string
    confirmPassword: string
    isAgreement: boolean | string
    mobile: string
    password: string
    smsCode: string
}

const form = ref<FormInstance>()

const ruleForm = reactive<IForm>({
    account: '',
    confirmPassword: '',
    isAgreement: false,
    mobile: '',
    password: '',
    smsCode: '',
})

function validateUserName(_rule: FormItemRule, value: string, callback: Fn): void {
    const pattern = /^[a-z0-9\u4E00-\u9FA5]{2,20}$/i
    if (!value) {
        callback(new Error('请输入用户名'))
    }
    if (value.length < 2 || value.length > 20) {
        callback(new Error('用户名长度在2-20个字符之间'))
    }
    if (pattern.test(value))
        callback()
    else
        callback(new Error('用户名禁止输入特殊字符'))
}

function validatePasswordComplex(_rule: FormItemRule, value: string, callback: Fn): void {
    const pattern = /^(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*,._])[\w!@#$%^&*,\\.]{6,20}$/

    if (pattern.test(value))
        callback()
    else
        callback(new Error('密码必须包含大小写字母，特殊字符和数字，且长度不低于6位'))
}

function validateConfirmPassword(_rule: FormItemRule, value: string, callback: Fn): void {
    if (value === '')
        callback(new Error('请再次输入密码'))
    else if (value !== ruleForm.password)
        callback(new Error('两次输入密码不一致!'))
    else
        callback()
}

const rules = reactive<FormRules<IForm>>({
    account: [
        {
            required: true,
            validator: validateUserName,
        },
    ],
    confirmPassword: [
        {
            required: true,
            trigger: 'blur',
            validator: validateConfirmPassword,
        },
    ],
    isAgreement: [
        {
            message: '请勾选协议',
            required: true,
            type: 'boolean',
        },
    ],
    mobile: [
        {
            message: '请输入手机号',
            required: true,
        },
        {
            message: '手机号码格式不正确',
            pattern: /^1[3-9]\d{9}$/,
            trigger: 'blur',
        },
    ],
    password: [
        {
            message: '请输入密码',
            required: true,
        },
        {
            trigger: 'blur',
            validator: validatePasswordComplex,
        },
    ],
    smsCode: [
        {
            message: '请输入验证码',
            required: true,
        },
    ],
})

const veryfyCodeFirstSending = ref(false)
const countdown = ref(0)
const verifyLabel = computed(() => {
    if (unref(veryfyCodeFirstSending)) {
        if (unref(countdown) > 0)
            return `${unref(countdown)}秒后重发`
        else
            return '重新发送'
    }
    else { return '发送验证码' }
})

const { isPending: isPendingSendSms, mutate: mutateSendSms } = useSendSms()
const { isPending: isPendingRegister, mutate: mutateRegister } = useRegister()

async function sendVerifyCode() {
    const valid = await unref(form)!.validateField('mobile')
    if (valid) {
        // 弹出拼图验证框, 验证是真人, 才发送短信, 先做拼图可以节省短信费用
        if (verifyRef.value.isHuman)
            sendSms()
        else
            verifyVisible.value = true
    }
}

function sendSms() {
    mutateSendSms({ mobile: ruleForm.mobile }, {
        onSuccess: () => {
            // 启动倒计时
            createMessage.success('验证通过')
            veryfyCodeFirstSending.value = true
            countdown.value = 60
            startCountdown()
        },
    })
}

function startCountdown() {
    const interval = setInterval(() => {
        countdown.value = countdown.value - 1
        if (unref(countdown) === 0)
            clearInterval(interval)
    }, 1000)
}

async function submitForm(formEl: FormInstance | undefined) {
    if (!formEl)
        return

    const valid = await formEl.validate()
    if (valid) {
        if (!ruleForm.isAgreement) {
            createMessage.warning('请勾选协议')
            return
        }
        mutateRegister({
            captcha: ruleForm.smsCode,
            isRegister: true,
            mobile: ruleForm.mobile,
            needCaptcha: true,
            password: ruleForm.password,
            userName: ruleForm.account,
        }, {
            onSuccess: () => {
                ElMessage.success('注册成功, 请登录')
                push('/login')
            },
        })
    }
}
</script>

<template>
    <ElForm ref="form"
            label-position="top"
            :model="ruleForm"
            :rules="rules"
            autocomplete="off"
            @submit.prevent
    >
        <div class="flex flex-col gap-12">
            <ElFormItem label="请输入用户名"
                        prop="account"
            >
                <el-input v-model.trim="ruleForm.account"
                          placeholder="请输入用户名"
                          maxlength="20"
                          size="large"
                />
            </ElFormItem>
        </div>

        <div class="flex flex-col gap-12">
            <ElFormItem label="密码"
                        prop="password"
            >
                <el-input v-model.trim="ruleForm.password"
                          placeholder="请输入密码"
                          autocomplete="new-password"
                          size="large"
                          maxlength="20"
                          type="password"
                          show-password
                />
            </ElFormItem>
        </div>

        <div class="flex flex-col gap-12">
            <ElFormItem label="确认密码"
                        prop="confirmPassword"
            >
                <el-input v-model.trim="ruleForm.confirmPassword"
                          placeholder="请再次输入密码"
                          size="large"
                          maxlength="20"
                          type="password"
                          show-password
                />
            </ElFormItem>
        </div>

        <div class="flex flex-col gap-12">
            <ElFormItem label="手机号"
                        prop="mobile"
            >
                <el-input v-model.trim="ruleForm.mobile"
                          maxlength="11"
                          placeholder="请输入手机号"
                          size="large"
                />
            </ElFormItem>
        </div>

        <div class="flex flex-col gap-12">
            <ElFormItem label="验证码"
                        prop="smsCode"
            >
                <div class="flex w-full items-center">
                    <el-input v-model="ruleForm.smsCode"
                              placeholder="请输入验证码"
                              size="large"
                              minlength="6"
                              maxlength="6"
                              class="flex-1"
                    />

                    <SubmitBtn type="primary"
                               native-type="button"
                               class="ml-8 h-40 w-100"
                               :disabled="countdown > 0"
                               :loading="isPendingSendSms"
                               @click="sendVerifyCode"
                    >
                        {{ verifyLabel }}
                    </SubmitBtn>
                </div>
            </ElFormItem>
        </div>

        <div class="flex flex-col gap-12">
            <ElFormItem prop="isAgreement">
                <el-checkbox v-model="ruleForm.isAgreement">
                    <span class="text-12">我已阅读并同意</span>
                </el-checkbox>

                <a class="text-12 text-red-500 cursor-pointer"
                   @click="serviceVisible = true"
                >《安居链服务协议》</a>

                <a class="text-12 text-red-500 cursor-pointer"
                   @click="policyVisible = true"
                >《隐私政策》</a>
            </ElFormItem>
        </div>

        <SubmitBtn type="primary"
                   native-type="submit"
                   class="btn rounded-3 text-#fff lh-48 text-center w-full cursor-pointer"
                   size="large"
                   :loading="isPendingRegister"
                   @click="submitForm(form)"
        >
            注册
        </SubmitBtn>
    </ElForm>

    <ServiceAgreement v-model:visible="serviceVisible" />

    <PolicyAgreement v-model:visible="policyVisible" />

    <SlideVerify ref="verifyRef"
                 v-model:visible="verifyVisible"
                 @success="sendSms"
    />
</template>

<style lang="scss" scoped>
@function toVw($px) {
    @return #{calc(#{$px} * 100 / 1920 * 1vw)};
}
@function toVh($px) {
    @return #{calc(#{$px} * 100 / 1080 * 1vh)};
}
.btn {
    margin-bottom: toVh(30);
}
</style>
